package com.yunhe.option.service.base.impl;

import com.alibaba.fastjson.JSON;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.model.PageParam;
import com.yunhe.common.util.CollectionUtil;
import com.yunhe.common.util.QueryUtil;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import com.yunhe.option.domain.base.Enum;
import com.yunhe.option.domain.base.ImportEnumItems;
import com.yunhe.option.domain.base.Item;
import com.yunhe.option.repository.base.EnumRepository;
import com.yunhe.option.service.base.EnumService;
import com.yunhe.option.service.base.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @ClassName EnumSerivceImpl
 * @Description TODO
 * @Author HeTao
 * @Date 2021/2/26 14:30
 * @Version 1.0
 **/
@Service
public class EnumServiceImpl implements EnumService {
    @Autowired
    private EnumRepository enumRepository;

    @Autowired
    private ItemService itemService;

    @Autowired
    private RedisClient redisClient;

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Enum createEnum(Enum enums) throws UniqueConstraintsException, ArgumentErrorException {
        enums.setId(null);
        if(StringUtil.isEmpty(enums.getSn())){
            enums.setSn(String.valueOf(System.currentTimeMillis()));
        }
        processBeforeSave(enums);
        Enum newEnum = enumRepository.save(enums);
        return newEnum;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Enum updateEnum(Enum enums) throws ArgumentErrorException, UniqueConstraintsException {
        Enum anEnum = enumRepository.findById(enums.getId()).orElse(null);
        if(anEnum  != null){
            throw new ArgumentErrorException("对应的枚举id为："+enums.getId()+"不存在!");
        }
        List<Item> items = (List<Item>) itemService.getItemByEnumName(anEnum.getTitle());
        enums.setItems(items);
        processBeforeSave(enums);
        Enum newEnum = enumRepository.save(enums);
        return newEnum;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void delete(Long id) throws ArgumentErrorException {
        List<Item> items = (List<Item>) itemService.findByEnumId(id);
        if(!CollectionUtil.isEmpty(items)){
            throw new ArgumentErrorException("该枚举存在对应的条目！");
        }
        enumRepository.deleteById(id);
    }

    @Override
    public Enum getEnumById(Long id) throws ArgumentErrorException {
        Enum anEnum = enumRepository.findById(id).orElse(null);
        if(anEnum  == null){
            throw new ArgumentErrorException("对应的枚举id为："+id+"不存在!");
        }
        return anEnum;
    }

    @Override
    public Iterable<Enum> getEnumByCondition(PageParam pageParam) {
        Iterable<Enum> result = null;
        if(QueryUtil.needPaging(pageParam)){
            Pageable pageable = QueryUtil.getPageRequest(pageParam);
            result = enumRepository.findAllEnums(pageable);
        }else {
            result = enumRepository.findAllEnums();
        }
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public List<String> importEnumAndItems(List<ImportEnumItems> importEnumItems) throws UniqueConstraintsException, ObjectNotFoundException, ArgumentErrorException {
        List<String> errMessage = new ArrayList<>();
        Long num = 0L;
        if(!CollectionUtil.isEmpty(importEnumItems)){
            //处理excel 获取的数据
            //根据枚举name 分组
            Map<String, List<ImportEnumItems>> map = importEnumItems.stream().collect(Collectors.groupingBy(importEnumItem -> {
                return importEnumItem.getEnumName();
            }));
            List<Enum> enumList = new ArrayList<>();
            if(!CollectionUtil.isEmpty(map)){
                for (Map.Entry<String, List<ImportEnumItems>> entrySet : map.entrySet()) {
                    //处理枚举name 里面条目数据
                    Enum enums = new Enum();
                    enums.setName(entrySet.getKey());
                    List<ImportEnumItems> values = entrySet.getValue();
                    List<String> collect = values.stream().map(value -> value.getItemCode()).collect(Collectors.toList());
                    long count = collect.stream().distinct().count();
                    if(count < values.size()){
                        errMessage.add("枚举类型为"+entrySet.getKey()+"存在相同的条目！");
                    }
                    if(!CollectionUtil.isEmpty(values)){
                        enums.setTitle(values.get(0).getEnumTitle());
                        //获得一级条目对象
                        List<ImportEnumItems> topItems = values.stream().filter(importEnumItem -> {
                            return StringUtil.isEmpty(importEnumItem.getpItemCode());
                        }).collect(Collectors.toList());
                        //获得所有子条目
                        List<ImportEnumItems> childItems = values.stream().filter(importEnumItem -> {
                            return !StringUtil.isEmpty(importEnumItem.getpItemCode());
                        }).collect(Collectors.toList());
                        List<Item> items = new ArrayList<>();
                        for (ImportEnumItems topItem : topItems) {
                            Item item = new Item();
                            item.setCode(topItem.getItemCode());
                            item.setTitle(topItem.getItemTitle());
                            recursionGetChildItem(item,childItems);
                            items.add(item);
                        }
                        enums.setItems(items);

                    }
                    enumList.add(enums);
                }
            }
            if(CollectionUtil.isEmpty(errMessage)){
                //数据入库
                saveToDataBase(enumList);
            }

        }
        return errMessage;
    }

    @Override
    public int getTotalCount() {
        return (int) enumRepository.count();
    }

    @Override
    public Iterable<Enum> findAll() {
        return enumRepository.findAll();
    }

    private void saveToDataBase(List<Enum> enumList) throws ObjectNotFoundException, UniqueConstraintsException, ArgumentErrorException {
        if(!CollectionUtil.isEmpty(enumList)){
            for (Enum anEnum : enumList) {
                //校验当前枚举是否已经存在
                Enum byName = enumRepository.findByName(anEnum.getName());
                if(byName == null){
                    enumRepository.save(anEnum);
                }else {
                    List<Item> items = anEnum.getItems();
                    List<Item> itemByEnumName = (List<Item>) itemService.getItemByEnumName(anEnum.getName());
                    if(CollectionUtil.isEmpty(itemByEnumName)){
                        for (Item item : items) {
                            itemService.createItem(byName.getId(),null,item);
                        }
                    }else {
                        //比对新旧的条目，查看是否有相同的
                        List<String> names = items.stream()
                                .map(t -> itemByEnumName.stream().filter(s -> Objects.nonNull(t.getCode()) && Objects.nonNull(s.getCode()) && Objects.equals(t.getCode(), s.getCode())).findAny().orElse(null))
                                .filter(Objects::nonNull)
                                .map(r -> r.getName())
                                .collect(Collectors.toList());
                        if(CollectionUtil.isEmpty(names)){
                            for (Item item : items) {
                                itemService.createItem(byName.getId(),null,item);
                            }
                        }else {
                            throw new ArgumentErrorException("枚举类型为"+anEnum.getTitle()+"存在相同的条目！");
                        }
                    }
                }
                //查询，存放redis
                List<Item>  items = (List<Item>) itemService.getItemByItemCodeAndEnumName(anEnum.getName());
                if(!CollectionUtil.isEmpty(items)){
                    redisClient.set("ENUM_ITEM:"+anEnum.getName(), JSON.toJSONString(items));
                }
            }
        }
    }

    private void recursionGetChildItem(Item item, List<ImportEnumItems> childItems) {
        //将子条目根据父级code 分组
        Map<String, List<ImportEnumItems>> childItemMap = childItems.stream().collect(Collectors.groupingBy(importEnumItem -> importEnumItem.getpItemCode()));
        if(!CollectionUtil.isEmpty(childItemMap)){
            for (Map.Entry<String, List<ImportEnumItems>> entrySet : childItemMap.entrySet()) {
                if(item.getCode().equals(entrySet.getKey())){
                    List<ImportEnumItems> collect = childItems.stream().filter(importEnumItem ->
                            !item.getCode().equals(importEnumItem.getpItemCode())).collect(Collectors.toList());
                    List<Item> items = new ArrayList<>();
                    List<ImportEnumItems> values = entrySet.getValue();
                    if(!CollectionUtil.isEmpty(values)){
                        for (ImportEnumItems topItem : values) {
                            Item childItem = new Item();
                            childItem.setCode(topItem.getItemCode());
                            childItem.setTitle(topItem.getItemTitle());
                            recursionGetChildItem(childItem,collect);
                            items.add(childItem);
                        }
                    }
                    item.setChildren(items);
                }
            }
        }
    }

    private void processBeforeSave(Enum enums) throws UniqueConstraintsException, ArgumentErrorException {
        if(StringUtil.isEmpty(enums.getName()) || StringUtil.isEmpty(enums.getTitle())){
            throw new ArgumentErrorException("枚举编码、枚举名称不能为空！");
        }
        //校验name是否存在
        Enum enumByName = enumRepository.findByName(enums.getName());
        if(enumByName != null){
            if(enums.getId() == null || enums.getId().longValue() != enumByName.getId().longValue()){
                throw new UniqueConstraintsException("对应的枚举编码为："+enums.getName()+"已经存在!");
            }
        }


    }
}
